package com.alinesno.cloud.initializr.starter.service.impl;

import java.util.List;
import java.util.Map;

import javax.lang.exception.RpcServiceRuntimeException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSONObject;
import com.alinesno.cloud.common.core.service.impl.IBaseServiceImpl;
import com.alinesno.cloud.initializr.starter.bean.DependencyUtils;
import com.alinesno.cloud.initializr.starter.bean.templates.MavenTemplateRootBean;
import com.alinesno.cloud.initializr.starter.cicd.deploy.k8s.api.DeploymentApi;
import com.alinesno.cloud.initializr.starter.cicd.deploy.k8s.api.IngressApi;
import com.alinesno.cloud.initializr.starter.cicd.deploy.k8s.api.ServiceApi;
import com.alinesno.cloud.initializr.starter.cicd.deploy.k8s.bean.DeploymentBean;
import com.alinesno.cloud.initializr.starter.cicd.deploy.k8s.bean.IngressBean;
import com.alinesno.cloud.initializr.starter.cicd.deploy.k8s.bean.ServiceBean;
import com.alinesno.cloud.initializr.starter.cicd.gitlab.common.Gitlab4jClient;
import com.alinesno.cloud.initializr.starter.cicd.gitlab.common.Gitlab4jProperties;
import com.alinesno.cloud.initializr.starter.cicd.jenkins.bean.MavenJobBean;
import com.alinesno.cloud.initializr.starter.cicd.jenkins.bean.NpmJobBean;
import com.alinesno.cloud.initializr.starter.cicd.jenkins.service.MavenJobService;
import com.alinesno.cloud.initializr.starter.codegen.init.InitProjectService;
import com.alinesno.cloud.initializr.starter.codegen.seedgen.utils.ProjectVelocityUtils;
import com.alinesno.cloud.initializr.starter.constants.JenkinsJobStatusEnums;
import com.alinesno.cloud.initializr.starter.constants.PackageTypeEnums;
import com.alinesno.cloud.initializr.starter.dto.BuildDto;
import com.alinesno.cloud.initializr.starter.entity.BuildApplicationTemplatesEntity;
import com.alinesno.cloud.initializr.starter.entity.BuildGitEntity;
import com.alinesno.cloud.initializr.starter.entity.BuildProjectParamsEntity;
import com.alinesno.cloud.initializr.starter.entity.ProjectInfoEntity;
import com.alinesno.cloud.initializr.starter.enums.LanguageEnum;
import com.alinesno.cloud.initializr.starter.repository.BuildProjectInfoMapper;
import com.alinesno.cloud.initializr.starter.seedgen.bean.ProjectInfoDto;
import com.alinesno.cloud.initializr.starter.service.IBuildApplicationTemplatesService;
import com.alinesno.cloud.initializr.starter.service.IBuildGitService;
import com.alinesno.cloud.initializr.starter.service.IBuildProjectInfoService;
import com.alinesno.cloud.rest.gateway.adapter.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.extensions.Ingress;

/**
 * 【请填写功能名称】Service业务层处理
 *
 * @author alinesno
 * @date 2021-06-05
 */
@Service
public class BuildProjectInfoServiceImpl extends IBaseServiceImpl<ProjectInfoEntity, BuildProjectInfoMapper>
		implements IBuildProjectInfoService {

	// 日志记录
	private static final Logger log = LoggerFactory.getLogger(BuildProjectInfoServiceImpl.class);

	@Autowired
	private InitProjectService initProjectService;

	@Autowired
	private IBuildApplicationTemplatesService templatesService;

	@Autowired
	private DeploymentApi deploymentApi;

	@Autowired
	private ServiceApi serviceApi;

	@Autowired
	private IBuildProjectInfoService buildProjectInfoService;

	@Autowired
	private IngressApi ingressApi;

	@Autowired
	private IBuildGitService buildGitService;

	@Autowired
	private MavenJobService jobService;

	private static final String DEFAULT_PROJECT_PRE = "alinesno-cloud-";

	@Override
	public ProjectInfoEntity uploadGitProject(ProjectInfoDto info) {

		// 保存项目
		ProjectInfoEntity e = new ProjectInfoEntity(); // optional.get();
		e.setIcons(info.getProjectIcon());
		e.setProjectName(info.getProjectName());
		e.setProjectCode(info.getProjectCode());
		e.setNamespace(info.getNamespace());
		e.setArtifactId(info.getArtifactId());
		e.setGroupId(info.getGroupId());
		e.setAlinesnoUI(info.getAlinesnoUI());
		e.setDomainName(info.getDomain());
		e.setCheckEnv(info.getCheckEnv());
		e.setGeneratorDemo(info.getGeneratorDemo());
		e.setJdk(info.getJdk());
		e.setPackageType(info.getPackageType());
		e.setLanguage(getLanguge(info.getPackageType()));
		e.setAlinesnoVersion(info.getAlinesnoVersion());
		e.setDependency(JSONUtil.toJsonStr(info.getDependency()));
		e.setOperatorId(info.getOperatorId());

		buildProjectInfoService.save(e);

		info.setProjectId(e.getId());
		info.setGitGroupName(info.getGroup().getName());
		info.setRepositoryName(
				StringUtils.isBlank(info.getRepositoryName()) ? info.getArtifactId() : info.getRepositoryName());

		Map<String, byte[]> data = null;

		if (PackageTypeEnums.MAVEN.value().equals(info.getPackageType())) {
			data = ProjectVelocityUtils.genJavaProjectSeedByte(info);
		} else if (PackageTypeEnums.NPM.value().equals(info.getPackageType())) {
			data = ProjectVelocityUtils.genNpmProjectSeedByte(info, false);
		}

		try {
			BuildGitEntity e1 = buildGitService.getById(info.getGitTypeId());

			Gitlab4jProperties p = new Gitlab4jProperties();
			p.setPrivateToken(e1.getAccessPrivateToken());
			p.setUrl(e1.getGitHost());
			p.setUser(e1.getGitUsername());

			Gitlab4jClient client = new Gitlab4jClient();
			client.setProperties(p);

			info = initProjectService.initRepo(info, data, client);

			e.setGitProjectId(info.getGitProjectId());
			e.setGitProjectLink(info.getGitProjectLink());
			e.setGitRunnersToken(info.getGitRunnersToken());

			update(e);

			return e;
		} catch (Exception e1) {
			e1.printStackTrace();
			throw new RpcServiceRuntimeException(e1);
		}
	}

	private String getLanguge(String packageType) {
		if (PackageTypeEnums.MAVEN.value().equals(packageType)) {
			return LanguageEnum.JAVA.name();
		} else if (PackageTypeEnums.NPM.value().equals(packageType)) {
			return LanguageEnum.NODE.name();
		}
		return null;
	}

	@Override
	public void publicDeployment(String projectId, BuildProjectParamsEntity params) {
		ProjectInfoEntity p = getById(projectId);

		// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 添加deployment_start >>>>>>>>>>>>>>>>>>>>>>>
		DeploymentBean bean = new DeploymentBean();

		int containerPort = getPort(params);

		bean.setNamespace(p.getNamespace());
		bean.setName(p.getArtifactId());
		bean.setContainerPort(containerPort);
		bean.setPullSecret(p.getDockerSecret());
		bean.setImage(p.getImageName());

		// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TODO 测试数据_start >>>>>>>>>>>>>>>>>>>>>>
		bean.setNamespace("test");
		bean.setPullSecret("docker-login");
		// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TODO 测试数据_end >>>>>>>>>>>>>>>>>>>>>>

		Deployment deployment = deploymentApi.createDeployment(bean);
		log.debug("deployment = {}", deployment);

		// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 添加deployment_end >>>>>>>>>>>>>>>>>>>>>>>
	}

	public int getPort(BuildProjectParamsEntity params) {
		int containerPort = 8080;
		if (params != null && StringUtils.isNotEmpty(params.getContainerPort())) {
			containerPort = Integer.parseInt(params.getContainerPort());
		}
		return containerPort;
	}

	@Override
	public void publicService(String projectId, BuildProjectParamsEntity params) {
		ProjectInfoEntity p = getById(projectId);

		// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 添加service_start >>>>>>>>>>>>>>>>>>>>>>>
		ServiceBean sbean = new ServiceBean();

		int containerPort = getPort(params);

		sbean.setNamespace(p.getNamespace());
		sbean.setServiceName(p.getArtifactId());
		sbean.setPort(containerPort);
		sbean.setTargetPort(containerPort);
		sbean.setSelecterApp(p.getArtifactId());

		// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TODO 测试数据_start >>>>>>>>>>>>>>>>>>>>>>
		sbean.setNamespace("test");

		io.fabric8.kubernetes.api.model.Service service = serviceApi.createService(sbean);
		log.debug("Service = {}", service);
		// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 添加service_end >>>>>>>>>>>>>>>>>>>>>>>

	}

	@Override
	public void publicIngress(String projectId, BuildProjectParamsEntity params) {
		ProjectInfoEntity p = getById(projectId);

		int containerPort = getPort(params);

		IngressBean bean = new IngressBean();
		bean.setDomain(p.getDomainName());
		bean.setIngressName(p.getArtifactId());
		bean.setNamespace(p.getNamespace());

		bean.setServiceName(p.getArtifactId());
		bean.setServicePort(containerPort);

		// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TODO 测试数据_start >>>>>>>>>>>>>>>>>>>>>>
		bean.setNamespace("test");

		Ingress ingress = ingressApi.createIngress(bean);
		log.debug("ingress = {}", ingress);

	}

	@Override
	public String buildDocker(String projectId, BuildDto dto) {

		Assert.hasLength(projectId, "应用为空");

		// 判断应用是否在构建中
		ProjectInfoEntity p = getById(projectId);
		if (JenkinsJobStatusEnums.RUNING.value().equals(p.getJenkinsJobStatus())) {
			Assert.isTrue(true, "应用已经正在构建中");
		}

		p.setLanguage(LanguageEnum.NODE.name());
//		p.setNamespace("");

		String jenkinsJobName = "";

		// 1. 判断语言类型
		// 2. 开始构建工程

		if (p.getLanguage().equals(LanguageEnum.JAVA.name())) {

			MavenJobBean bean = new MavenJobBean();

			bean.setBranches(dto.getBranches());
			bean.setGitPath(p.getGitProjectLink());
			bean.setName(p.getArtifactId());
			bean.setArtifactid(p.getArtifactId());

			jobService.createMavenJob(bean);
			jenkinsJobName = bean.getJobName();
			p.setJenkinsJobName(bean.getJobName());

		} else if (p.getLanguage().equals(LanguageEnum.NODE.name())) {

			NpmJobBean bean = new NpmJobBean();

			bean.setBranches(dto.getBranches());
			bean.setGitPath(p.getGitProjectLink());
			bean.setName(p.getArtifactId());

			jobService.createNpmJob(bean);
			jenkinsJobName = bean.getJobName();
			p.setJenkinsJobName(bean.getJobName());
		}

		p.setJenkinsJobStatus(JenkinsJobStatusEnums.RUNING.value());

		this.updateById(p);

		return jenkinsJobName;
	}

	@Override
	public void deleteJenkinsJob(String jobName) {
		jobService.deleteJob(jobName); // 删除任务

		// 更新任务状态
	}

	@Override
	public boolean isFinishJob(String jenkinsJobName) {
		return jobService.isFinish(jenkinsJobName);
	}

	@Override
	public void publicK8S(String projectId, BuildProjectParamsEntity params) {
		try {
			this.publicDeployment(projectId, params);
		} catch (Exception e) {
			log.error("发布deployement异常:{}", e.getMessage());
		}
		try {
			this.publicService(projectId, params);
		} catch (Exception e) {
			log.error("发布service异常:{}", e.getMessage());
		}
		try {
			this.publicIngress(projectId, params);
		} catch (Exception e) {
			log.error("发布ingress异常:{}", e.getMessage());
		}
	}

	@Override
	public ProjectInfoEntity uploadGitProject(ProjectInfoDto info, String templateId) {

		Assert.hasLength(templateId, "模板id为空.");
		Assert.hasLength(info.getProjectCode(), "项目标识为空.");

		BuildApplicationTemplatesEntity templateEntity = templatesService.getById(templateId);
		Assert.notNull(templateEntity, "模板实体为空，请确认模板是否存在.");

		String jsonStr = templateEntity.getMavenXml();
		Assert.hasLength(jsonStr, "模板内容未上传.");

		MavenTemplateRootBean root = DependencyUtils.root(jsonStr);
		log.debug("dependencyList:{}", JSONObject.toJSONString(root));

		// >>>>>>>>>>>>>>>>>>> TODO 设置默认值_start >>>>>>>>>>>>>>>>>>>
		String projectCode = info.getProjectCode(); // 项目唯一标识

		String objectId = IdUtil.objectId();
		;
		String domain = objectId + "." + projectCode;
		String artifactId = DEFAULT_PROJECT_PRE + projectCode;
		String groupId = DEFAULT_PROJECT_PRE.replace("-", ".") + projectCode;
		String checkEnv = "true";
		String generatorDemo = "true";
		String jdk = "11";
		String packageType = PackageTypeEnums.MAVEN.value();
		String language = LanguageEnum.JAVA.name();
		String alinesnoVersion = "1.4.1";
		String namespace = info.getNamespace();
		String[] deployment = { "1", "2" };
		// >>>>>>>>>>>>>>>>>>> 设置默认值_end >>>>>>>>>>>>>>>>>>>

		info.setDomain(domain);
		info.setArtifactId(artifactId);
		info.setGroupId(groupId);
		info.setCheckEnv(checkEnv);
		info.setGeneratorDemo(generatorDemo);
		info.setJdk(jdk);
		info.setLanguage(language);
		info.setPackageType(packageType);
		info.setAlinesnoVersion(alinesnoVersion);
		info.setNamespace(namespace);
		info.setDependency(deployment);

		info.setTemplateBean(root);

		return this.uploadGitProject(info);
	}

	@Override
	public List<ProjectInfoEntity> queryProjectInfoByCode(String projectCode) {
		Assert.hasLength(projectCode, "项目标识不能为空");

		QueryWrapper<ProjectInfoEntity> queryWrapper = new QueryWrapper<ProjectInfoEntity>();
		queryWrapper.eq("project_code", projectCode);

		List<ProjectInfoEntity> es = this.list(queryWrapper);

		return es;
	}

	/**
	 * 保存部分信息
	 *
	 * @param dto
	 * @return
	 */
	@Override
	public ProjectInfoEntity halfSave(ProjectInfoDto info) {
		// 保存生成工程信息
		ProjectInfoEntity e = new ProjectInfoEntity();

		e.setIcons(info.getProjectIcon());
		e.setProjectName(info.getProjectName());
		e.setProjectCode(info.getProjectCode());
		e.setNamespace(info.getNamespace());
		e.setArtifactId(info.getArtifactId());
		e.setGroupId(info.getGroupId());
		e.setAlinesnoUI(info.getAlinesnoUI());
		e.setDomainName(info.getDomain());
		e.setCheckEnv(info.getCheckEnv());
		e.setGeneratorDemo(info.getGeneratorDemo());
		e.setJdk(info.getJdk());
		e.setPackageType(info.getPackageType());
		e.setLanguage(getLanguge(info.getPackageType()));
		e.setAlinesnoVersion(info.getAlinesnoVersion());
		e.setDependency(JSONUtil.toJsonStr(info.getDependency()));

		e.setOperatorId(info.getOperatorId());

		save(e);
		return e;
	}

	@Override
	public ProjectInfoEntity uploadGiteeProject(ProjectInfoDto info) {
		// 保存项目
		ProjectInfoEntity e = new ProjectInfoEntity(); // optional.get();
		e.setIcons(info.getProjectIcon());
		e.setProjectName(info.getProjectName());
		e.setProjectCode(info.getProjectCode());
		e.setNamespace(info.getNamespace());
		e.setArtifactId(info.getArtifactId());
		e.setGroupId(info.getGroupId());
		e.setAlinesnoUI(info.getAlinesnoUI());
		e.setDomainName(info.getDomain());
		e.setCheckEnv(info.getCheckEnv());
		e.setGeneratorDemo(info.getGeneratorDemo());
		e.setJdk(info.getJdk());
		e.setPackageType(info.getPackageType());
		e.setLanguage(getLanguge(info.getPackageType()));
		e.setAlinesnoVersion(info.getAlinesnoVersion());
		e.setDependency(JSONUtil.toJsonStr(info.getDependency()));
		e.setOperatorId(info.getOperatorId());

		buildProjectInfoService.save(e);

		info.setProjectId(e.getId());
//		info.setGitGroupName(info.getGroup().getName());
		info.setRepositoryName(
				StringUtils.isBlank(info.getRepositoryName()) ? info.getArtifactId() : info.getRepositoryName());

		Map<String, byte[]> data = null;

		if (PackageTypeEnums.MAVEN.value().equals(info.getPackageType())) {
			data = ProjectVelocityUtils.genJavaProjectSeedByte(info);
		} else if (PackageTypeEnums.NPM.value().equals(info.getPackageType())) {
			data = ProjectVelocityUtils.genNpmProjectSeedByte(info, false);
		}

		try {
			BuildGitEntity e1 = buildGitService.getById(info.getGitTypeId());

			info = initProjectService.initGiteeRepo(info, data, e1);

			e.setGitProjectId(info.getGitProjectId());
			e.setGitProjectLink(info.getGitProjectLink());
			e.setGitRunnersToken(info.getGitRunnersToken());

			update(e);

			return e;
		} catch (Exception e1) {
			e1.printStackTrace();
			throw new RpcServiceRuntimeException(e1);
		}
	}

	@Override
	public ProjectInfoEntity uploadGiteaProject(ProjectInfoDto info) {
		// 保存项目
		ProjectInfoEntity e = new ProjectInfoEntity(); // optional.get();
		e.setIcons(info.getProjectIcon());
		e.setProjectName(info.getProjectName());
		e.setProjectCode(info.getProjectCode());
		e.setNamespace(info.getNamespace());
		e.setArtifactId(info.getArtifactId());
		e.setGroupId(info.getGroupId());
		e.setAlinesnoUI(info.getAlinesnoUI());
		e.setDomainName(info.getDomain());
		e.setCheckEnv(info.getCheckEnv());
		e.setGeneratorDemo(info.getGeneratorDemo());
		e.setJdk(info.getJdk());
		e.setPackageType(info.getPackageType());
		e.setLanguage(getLanguge(info.getPackageType()));
		e.setAlinesnoVersion(info.getAlinesnoVersion());
		e.setDependency(JSONUtil.toJsonStr(info.getDependency()));
		e.setOperatorId(info.getOperatorId());

		buildProjectInfoService.save(e);

		info.setProjectId(e.getId());
		// info.setGitGroupName(info.getGroup().getName());
		info.setRepositoryName(
				StringUtils.isBlank(info.getRepositoryName()) ? info.getArtifactId() : info.getRepositoryName());

		Map<String, byte[]> data = null;

		if (PackageTypeEnums.MAVEN.value().equals(info.getPackageType())) {
			data = ProjectVelocityUtils.genJavaProjectSeedByte(info);
		} else if (PackageTypeEnums.NPM.value().equals(info.getPackageType())) {
			data = ProjectVelocityUtils.genNpmProjectSeedByte(info, false);
		}

		try {
			BuildGitEntity e1 = buildGitService.getById(info.getGitTypeId());

			info = initProjectService.initGiteaRepo(info, data, e1);

			e.setGitProjectId(info.getGitProjectId());
			e.setGitProjectLink(info.getGitProjectLink());
			e.setGitRunnersToken(info.getGitRunnersToken());

			update(e);

			return e;
		} catch (Exception e1) {
			e1.printStackTrace();
			throw new RpcServiceRuntimeException(e1);
		}
	}
}
